package com.zret.oasys.operation.attendance;

import java.io.IOException;
import java.io.PrintWriter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.JSONObject;

import com.google.gson.Gson;
import com.google.gson.JsonParseException;
import com.zret.face.entity.check.CheckFaceRootBean;
import com.zret.face.entity.select.SelectFaceJsonRootBean;
import com.zret.facetools.FaceBDTools;
import com.zret.facetools.GsonUtils;
import com.zret.oasys.entity.Attence;
import com.zret.oasys.entity.Emp;
import com.zret.oasys.json.entity.FaceLoginJson;
import com.zret.oasys.service.AttendanceService;
import com.zret.oasys.service.EmpService;
import com.zret.oasys.service.impl.AttendanceServiceImpl;
import com.zret.oasys.service.impl.EmpServiceImpl;

/**
 * 人脸识别登录，人脸识别登录成功进行考勤处理
 * 
 * @author yuebin
 *
 */
public class FaceLogin implements AttendanceServletOperation {

	private  SimpleDateFormat simpl = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	private  SimpleDateFormat simp2 = new SimpleDateFormat("yyyy-MM-dd");
	private  SimpleDateFormat simp3 = new SimpleDateFormat("HH:mm:ss");
	AttendanceService attendanceSerice = new AttendanceServiceImpl();
	Gson gson = new Gson();
	
	
	@Override
	public void doOperation(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 设置编码
		request.setCharacterEncoding("utf-8");
		response.setContentType("application/json;charset=utf-8");
		PrintWriter out = response.getWriter();
		// 获取图片数据
		String imgbaseString = request.getParameter("imagebast64");
		// 去掉数据头
		String[] imgs = imgbaseString.split("data:image/png;base64,");
		// 拼接字符串
		String imgbase64 = "";
		for (int i = 0; i < imgs.length; i++) {
			imgbase64 += imgs[i];
		}
		// System.out.println("imgbase64:"+imgbase64);
		// 调用人脸检测
		JSONObject faceChecking = FaceBDTools.faceChecking(imgbase64);
		String checkjsonstring = faceChecking.toString();
		// System.out.println(string);
		// 写入实体类
		try {
			CheckFaceRootBean checkRoot = GsonUtils.fromJson(checkjsonstring, CheckFaceRootBean.class);
			int error_code = checkRoot.getError_code();
			String error_msg = checkRoot.getError_msg();
			// System.out.println(error_code+error_msg);
			// 如果人脸检测状态码和信息都是正常才执行人脸搜索
			if (error_code == 0 && "SUCCESS".equals(error_msg)) {
				// 执行人脸搜索
				JSONObject selectRoot = FaceBDTools.faceSelect(imgbase64);
				String selectjsonString = selectRoot.toString();
				// 写入实体类
				SelectFaceJsonRootBean selRoot = GsonUtils.fromJson(selectjsonString, SelectFaceJsonRootBean.class);
				// 获取相应的信息//53行到56行可能会出现异常,比如没有某个人在人脸库里面搜索就会出现异常
				try {
					int sel_errorcode = selRoot.getError_code();
					String sel_error_msg = selRoot.getError_msg();
					double sel_score = selRoot.getResult().getUser_list().get(0).getScore();// 要大于80分才能匹配到
					String user_id = selRoot.getResult().getUser_list().get(0).getUser_id();// 用户id

					if (sel_errorcode == 0 && "SUCCESS".equals(error_msg) && sel_score >= 80) {

						// 解析用户id
						int empid = Integer.parseInt(user_id);
						// 获取当前时间
						Date now = new Date();
						String attencetime = simpl.format(now);
						// 设置要传递信息标志，后面要使用
						String msg = "";
						// 调用考勤方法（目前实现到岗，迟到），获取员工对象，并调用业务费层写入数据
						// Attence attence = new Attence(empid, attencetime, "到岗");
						// 用户在非上班时间用人脸登录考勤系统或者其他情况是，调用getAttendance()不创建对象的
						Attence attence = getAttendance(empid);
						boolean flag = false;
						if (attence != null) {
							flag = attendanceSerice.addAttendance(attence);
							// 如果不为null那就提取考勤状态,设置在msg上
							msg = attence.getAttencetype();
						}

						// 用户在非上班时间用人脸登录考勤系统或者其他情况是，调用getAttendance()不创建对象的
						if (attence == null) {
							msg = "不进行考勤记录";
						}else if ("迟到".equals(attence.getAttencetype())) {
							msg = "迟到，下次要注意";
						}else if ("到岗".equals(attence.getAttencetype())) {
							msg = "到岗，再接再厉！";
						}
						// 把打卡成功的提示传值和员工id设置在session和员工的姓名和职位传入
						// 得到用户的职位和姓名信息
						EmpService empservice=new EmpServiceImpl();
						Emp emp = empservice.getEmpsById(empid);
						String empname = emp.getEmpname();//员工姓名
						String position = emp.getPosition();//员工职位
						
						HashMap hashMap = new HashMap();
						hashMap.put("empid", empid);
						hashMap.put("facelogin", "人脸识别登录成功");
						hashMap.put("msg", msg);
						hashMap.put("empname", empname);
						hashMap.put("position", position);
						// 获取到用户的id，把用户id设置属性在session  hashMap
						request.getSession().setAttribute("emp", hashMap);

						// 1是人脸识别登录成功2是人脸检测失败3是查无此人联系HR
						FaceLoginJson faceLoginJson = new FaceLoginJson("人脸识别成功", 1);

						String jsonmsg1 = gson.toJson(faceLoginJson);
						out.print(jsonmsg1);

						out.close();
					} else {
						// msg如果人脸搜索分数低于80获取或者出现错误信息，
						// 就提示用户请员工本人进行人脸登录或者人脸打卡
						// 1是人脸识别登录成功2是人脸检测失败3是查无此人联系HR
						FaceLoginJson faceLoginJson3 = new FaceLoginJson("请本公司员工进行人脸登录或者联系HR", 3);
						String jsonmsg3 = gson.toJson(faceLoginJson3);
						out.print(jsonmsg3);
						out.close();
					}

				} catch (Exception e) {
					// 如果出现异常的话，就传递json给前端告知用户，不是员工本人，请员工本人进行人脸登录或者人脸打卡
					// e.printStackTrace();
					// 1是人脸识别登录成功2是人脸检测失败3是查无此人联系HR
					FaceLoginJson faceLoginJson3_3 = new FaceLoginJson("请本公司员工进行人脸登录或者联系HR", 3);
					String jsonmsg3_3 = gson.toJson(faceLoginJson3_3);
					out.print(jsonmsg3_3);
					out.close();

				}

			} else {
				// 人脸检测失败的话，提示用户人脸检测失败，请重新录入
				// 1是人脸识别登录成功2是人脸检测失败3是查无此人联系HR

				FaceLoginJson faceLoginJson2 = new FaceLoginJson("请使用人脸进行识别，请重新录入", 2);
				String jsonmsg2 = gson.toJson(faceLoginJson2);

				out.print(jsonmsg2);
				out.close();

			}
		} catch (Exception e) {

			// 人脸检测出现异常的话，提示用户人脸检测失败，请重新录入
			// 1是人脸识别登录成功2是人脸检测失败3是查无此人联系HR

			FaceLoginJson faceLoginJson2_2 = new FaceLoginJson("请使用人脸进行识别，请重新录入", 2);
			String jsonmsg2_2 = gson.toJson(faceLoginJson2_2);
			out.print(jsonmsg2_2);
			out.close();

		}

	}

	// 定义考勤逻辑
	/**
	 * 考勤1.0，考勤到岗和迟到
	 * 
	 * @param empid 员工编号
	 * @return 员工对象
	 */
	public Attence getAttendance(int empid) {
		// 早上,允许用户提前打卡，在早上6点到9点半，下午打可以12点到1点半开始打卡（是属于正常打卡），
		// 公司6点下班。非上班时间或者非规定的时间打卡均为无效
		// 备注：这里用到2个SimpleDateFormat对象，定义在成员属性
		//[06:00:00,09:30:00]早上第一次到岗打卡    下午正常到岗第二次打卡[12:00:00,13:30:00] 
        //(09:30:00,12:00:00）早上第一次迟到打卡   下午迟到第二次打卡(13:30:00, 18:00:00]
		String mbeginTime = "06:00:00";
		String mendTime = "09:30:00";
		// 下午打卡时间
		String afbeginTime = "12:00:00";
		String afendTime = "13:30:00";
		//暂时测试
		//String afendTime = "23:30:00";
		// 下班时间
		String outTime = "18:00:00";
		//暂时测试
		//String outTime = "23:50:00";
		// 当前时间，日期和时间
		Date now = new Date();
		// 格式化当前时间，当前日期和时间
		String nowdatetime = simpl.format(now);
		//格式化当前时间，只有时间，不含日期并在转为Date格式
		String nowtime = simp3.format(now);

		// 当前日期，只有日期
		String nowdate = simp2.format(now);
		
		Date nowdatetimeDate = null;
		//只有时间
		Date mbegtimeDate=null;
		Date mafttimeDate=null;
		Date afbetimeDate=null;
		Date afendtimeDate=null;
		Date outtimehomeDate=null;
		Date nowtimeDate=null;
		// 创建考勤实体类为null，后面使用
		Attence attence = null;
		try {
			// 上午时间，上午签到开始时间-上午签到结束时间
			
			
			mbegtimeDate = simp3.parse(mbeginTime);//上午开始到岗只有时间
			mafttimeDate = simp3.parse(mendTime);//上午结束到岗只有时间
			
			// 下午时间，下午签到开始时间-下午签到结束时间
			
			
			afbetimeDate = simp3.parse(afbeginTime);//下午开始到岗只有时间
			afendtimeDate = simp3.parse(afendTime);//下午结束到岗只有时间
			
			// 下班时间解析
			
			outtimehomeDate = simp3.parse(outTime);//下班时间，只有时间
			
			// 当前日期和时间nowdatetime解析
			
			//当前时间解析
			nowtimeDate = simp3.parse(nowtime);//当前时间解析，只有时间
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// 1.调用考勤业务层查询,当天到岗的条数。业务层对象已经定义在成员属性。传入当前日期字符串格式
		List<Attence> comeList = attendanceSerice.getAttendanceByIdTypeTime(empid, nowdate, "到岗");
		int comeN = comeList.size();// 员工考勤到岗正常状态的查询个数
		// 2.调用考勤业务层查询，当天迟到的条数。
		List<Attence> lateList = attendanceSerice.getAttendanceByIdTypeTime(empid, nowdate, "迟到");
		int lateN = lateList.size();// 员工考勤迟到状态的查询个数
		//3.调用考勤业务层，查询某个时间范围[ ] 范围内记录的个数  下午正常到岗第二次打卡[12:00:00,13:30:00] 13:30:00
		List<Attence> aftimecomelist = attendanceSerice.getAttendByIdStarEndTimeType("1",empid, nowdate, "12:00:00", "13:30:00", "到岗");
		int aftimecomeN = aftimecomelist.size();
		//4.调用考勤业务层，查询( ] 查询某个时间范围内的记录个数，下午迟到第二次记录范围(13:30:00, 18:00:00] 18:00:00
		List<Attence> latetimelist = attendanceSerice.getAttendByIdStarEndTimeType("2", empid, nowdate, "13:30:00", "18:00:00", "迟到");
		int latetimeN = latetimelist.size();
		//5.调用考勤业务层，查询请假的记录个数，根据当前日期的模糊查询
		List<Attence> attlikedatetype = attendanceSerice.getAttendanceByIdLikeTypeDate(empid, nowdate, "假");
		int likedatetypeN = attlikedatetype.size();//当天没有请假的才执行，就是对于0
		
		// 我们规定员工考勤正常到岗2次记录。
		// 还需要控制下，正常打卡记录条数只能是有2条，n<=1
		// 1.也是分早上和下午 在规定的时间打卡(在岗)
		// 查询记录是根据当前日期和考勤状态来查询
		// 1.1如果早上没有打卡记录的话，也就是打卡记录为0的话，就记录一条记录
		// 1.2如果下午没有打卡记录的话，也就是打卡记录大于等于0且小于等于1的话( 0<=n<=1)，就记录一条记录,就保证一天正常打卡只能有2次
		// 1.正常打卡：进行时间比较 mbeginTimeDate<now<mendTimeDate
		//nowdatetimeDate.after(mbeginTimeDate) && nowdatetimeDate.before(mendTimeDate)
		//[06:00:00,09:30:00]早上第一次到岗打卡 
		if (nowtimeDate.getTime()>=mbegtimeDate.getTime()&&nowtimeDate.getTime()<=mafttimeDate.getTime()) {
			System.out.println("正常到岗");

			// 早上的时候，没有正常到岗记录数，当天没有请假的才执行，就是等于0
			if (comeN == 0&&likedatetypeN==0) {

				// 创建对象-正常到岗
				attence = new Attence(empid, nowdatetime, "到岗");

			}

		}
		// 下午的时候正常打卡（正常打卡到岗）
		// 1.正常打卡：进行时间比较 afbeginTimeDate<now<afendTimeDate
		//nowdatetimeDate.after(afbeginTimeDate) && nowdatetimeDate.before(afendTimeDate)
		//下午正常到岗打卡（只能打卡一次）
		//下午正常到岗第二次打卡[12:00:00,13:30:00] 
		else if (nowtimeDate.getTime()>=afbetimeDate.getTime()&&nowtimeDate.getTime()<=afendtimeDate.getTime()) {
			// 下午要么有1条，要么0条正常到岗记录数据
			//同时也要保证在当前日期[12:00:00,13:30:00] 时间范围内打卡条数只能有1条。那就是n<1，当天没有请假的才执行，就是对于0
			
			if (comeN <=1&&aftimecomeN<1&&likedatetypeN==0) {
				//执行一次就是加1

				// 创建对象-正常到岗
			
				attence = new Attence(empid, nowdatetime, "到岗");

			}
		
		}

		// 2.迟到：在上班时间超过了规定时间打卡均是迟到。
		// 2.还需要控制下，迟到一天最多只能记录2次迟到 n<=1
		// 2.1在工作期间属于超过规定打卡时间（在迟到时间进行打卡），我们在前面正常打卡已经设置了一天最多只能打卡2次
		// 用户可能已经打卡过了（n<=2）,也要分早上和下午判断
		// 2.1.1早上的时候，如果正常打卡记录为0,就记录为迟到
		// 2.2下午的时候，如果正常打卡记录为0或者1就记录为迟到
		// 早上迟到打卡
		// afendTimeDate<now<outTimeDate
		//nowdatetimeDate.after(mendTimeDate) && nowdatetimeDate.before(afbeginTimeDate)
		//(09:30:00,12:00:00）
		else if (nowtimeDate.getTime()>mafttimeDate.getTime()&&nowtimeDate.getTime()<afbetimeDate.getTime()) {
			// System.out.println("迟到");
			// mendTimeDate<now<afbeginTimeDate
			// 早上迟到时间段里面，迟到是0个记录和到岗记录也是0，当天没有请假的才执行，就是对于0
			if (comeN == 0 && lateN == 0&&likedatetypeN==0) {
				// 创建对象-迟到
				attence = new Attence(empid, nowdatetime, "迟到");
			}
			// 下午迟到打卡
			//nowdatetimeDate.after(afendTimeDate) && nowdatetimeDate.before(outTimeDate)
			//(13:30:00, 18:00:00]
		} else if (nowtimeDate.getTime()>afendtimeDate.getTime()&&nowtimeDate.getTime()<=outtimehomeDate.getTime()) {
			
			
			// 下午迟到时间段里面，迟到是0或者1个记录,到岗记录可能是1或者0
			//同时也要保证在当前日期(13:30:00, 18:00:00] 时间范围内打卡条数只能有1条。那就是n<1
			//当天没有请假的才执行，就是对于0
			if (comeN<=1 && lateN <= 1&&latetimeN<1&&likedatetypeN==0) {
				// 创建对象-迟到
				attence = new Attence(empid, nowdatetime, "迟到");
			}

		}

		return attence;

	}

}
